Expression Problem

Philip Wadlerが1998年に名付けた、プログラミング言語設計における根本的なトレードオフ。

データ型に対して、既存コードを修正せずに「新しいバリアント」と「新しい操作」の両方を追加できるか?

2つの拡張軸

新しいバリアント追加 新しい操作追加
判別共用体 + パターンマッチ 全パターンマッチ修正 関数を1つ追加するだけ
クラス + ポリモーフィズム サブクラスを1つ追加するだけ 全クラスにメソッド追加

具体例

判別共用体(関数型)

type Shape = Circle | Rectangle;  // ← バリアント

function area(s: Shape): number {  // ← 操作
  switch (s.type) {
    case "circle": return Math.PI * s.radius ** 2;
    case "rectangle": return s.width * s.height;
  }
}

ポリモーフィズム(OOP)

interface Shape {
  area(): number;  // ← 操作
}
class Circle implements Shape { area() { ... } }
class Rectangle implements Shape { area() { ... } }

「修正が必要」は悪いことか?

ここで重要な問い:パターンマッチの修正は「悪い結合」なのか?

考え方1:修正箇所が散らばるのは問題

考え方2:それは自然な依存関係

→ これは制御結合とは異なる。データの構造に依存しているだけで、内部実装の分岐ロジックを知っているわけではない。

本質:どちらの拡張が頻繁か

Expression Problemは「どちらが良い」ではなく「トレードオフの選択」。

多くのドメインでは両方が起きるため、完全な解決は難しい。

解決へのアプローチ

関連